home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-08-28 | 16.9 KB | 649 lines | [TEXT/MPS ] |
- /*
- File: Printer.cpp
-
- Contains: Base class for OpenDoc printing utility.
-
- Owned by: Jens Alfke
-
- Copyright: © 1995-96 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <2> 2/2/96 JA Filled in header comments
- <1> 2/2/96 JA first checked in
-
- To Do:
- */
-
-
- // -- OpenDoc --
-
- #ifndef _ALTPOINT_
- #include <AltPoint.h>
- #endif
-
- #ifndef SOM_ODCanvas_xh
- #include <Canvas.xh>
- #endif
-
- #ifndef SOM_ODClipboard_xh
- #include <Clipbd.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_Commands_defined
- #include <CmdDefs.xh>
- #endif
-
- #ifndef SOM_ODDispatcher_xh
- #include <Disptch.xh>
- #endif
-
- #ifndef SOM_ODFacet_xh
- #include <Facet.xh>
- #endif
-
- #ifndef SOM_ODFrame_xh
- #include <Frame.xh>
- #endif
-
- #ifndef SOM_ODMenuBar_xh
- #include <MenuBar.xh>
- #endif
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- #ifndef SOM_ODStorageSystem_xh
- #include <ODStor.xh>
- #endif
-
- #ifndef SOM_ODPart_xh
- #include <Part.xh>
- #endif
-
- #ifndef SOM_ODPlatformTypeList_xh
- #include <PfTypLs.xh>
- #endif
-
- #ifndef SOM_ODShape_xh
- #include <Shape.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdProps_defined
- #include <StdProps.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdTypes_defined
- #include <StdTypes.xh>
- #endif
-
- #ifndef SOM_ODStorageUnit_xh
- #include <StorageU.xh>
- #endif
-
- #ifndef SOM_ODTransform_xh
- #include <Trnsform.xh>
- #endif
-
- #ifndef SOM_ODWindowState_xh
- #include <WinStat.xh>
- #endif
-
- // -- OpenDoc Utilities --
-
- #ifndef _EXCEPT_
- #include <Except.h>
- #endif
-
- #ifndef _ITEXT_
- #include <IText.h>
- #endif
-
- #ifndef _DLOGUTIL_
- #include <DlogUtil.h>
- #endif
-
- #ifndef _ODDEBUG_
- #include <ODDebug.h>
- #endif
-
- #ifndef _ODNEW_
- #include <ODNew.h>
- #endif
-
- #ifndef _ODUTILS_
- #include <ODUtils.h>
- #endif
-
- #ifndef _STORUTIL_
- #include <StorUtil.h>
- #endif
-
- #ifndef _TEMPOBJ_
- #include <TempObj.h>
- #endif
-
- #ifndef _USERSRCM_
- #include <UseRsrcM.h>
- #endif
-
- // -- MacToolbox --
-
- #ifndef __GESTALT__
- #include <Gestalt.h>
- #endif
-
- #ifndef __GXGRAPHICS__
- #include <GXGraphics.h>
- #endif
-
- #ifndef __GXPRINTING__
- #include <GXPrinting.h>
- #endif
-
- #ifndef __PRINTING__
- #include <Printing.h>
- #endif
-
- #ifndef __TEXTUTILS__
- #include <TextUtils.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- // -- Printer --
- #define _PRINTER_PRIVATE_
- #ifndef _PRINTER_
- #include "Printer.h"
- #endif
-
- #pragma segment Printer
-
-
- //=================================================================================
- // CWithPrintingOpen helper class
- //
- // This is a stack-based object that opens printing in its constructor and
- // closes it in its destructor. This provides a simple and exception-safe way
- // to open up printing for the duration of a method or block.
- //=================================================================================
-
- CWithPrintingOpen::CWithPrintingOpen( CPrinter *printer )
- :fPrinter(kODNULL)
- {
- if( ! printer->IsPrintingOpen() ) {
- printer->OpenPrinting(); // Only open it if it wasn't open
- fPrinter = printer;
- }
- }
-
- CWithPrintingOpen::~CWithPrintingOpen( )
- {
- if( fPrinter )
- fPrinter->ClosePrinting(); // Only close if printing was already open
- }
-
-
- //=================================================================================
- // CWithDialogState helper class
- //
- // This is a stack-based object that sets up state for a modal dialog in its
- // constructor, and resets the state in the destructor. It deactivates the front
- // window, removes the "Redo" item from the Edit menu, and updates the Mac scrap.
- //=================================================================================
-
- CWithDialogState::CWithDialogState( Environment *ev, ODSession *session )
- {
- GetPort(&fPort);
- fEv = ev;
- fWindowState = session->GetWindowState(ev);
- TempODMenuBar menuBar = fWindowState->AcquireCurrentMenuBar(ev);
- fWindowState->DeactivateFrontWindows(ev);
- ODDialogBegin(ev, session, menuBar, kODNULL);
- InitCursor();
- }
-
- CWithDialogState::~CWithDialogState( )
- {
- ODDialogEnd();
- fWindowState->ActivateFrontWindows(fEv);
- SetPort(fPort);
- InitCursor();
- }
-
-
- //=================================================================================
- // BusyCursor helper function
- //=================================================================================
-
- void BusyCursor( )
- {
- SetCursor(*GetCursor(watchCursor));
- }
-
- //=================================================================================
- // CPrinter implementation
- //=================================================================================
-
- //---------------------------------------------------------------------------------
- // CPrinter::New [static method]
- //---------------------------------------------------------------------------------
-
- CPrinter* CPrinter::New( Environment *ev, ODStorageUnit *su )
- {
- // Create & initialize the appropriate type of CPrinter object:
-
- long gxVersion, gxPrintVersion;
- CPrinter *p;
-
- if ( Gestalt(gestaltGraphicsVersion, &gxVersion) == noErr &&
- Gestalt(gestaltGXPrintingMgrVersion, &gxPrintVersion) == noErr &&
- (void*)GXInitPrinting != (void*)kUnresolvedCFragSymbolAddress )
- p= new CGXPrinter;
- else
- p= new CQDPrinter;
-
- TRY{
- p->Initialize(ev,su);
- }CATCH_ALL{
- delete p;
- RERAISE;
- }ENDTRY
- return p;
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::CPrinter
- //---------------------------------------------------------------------------------
-
- CPrinter::CPrinter()
- {
- fDirty = kODFalse;
- fPrintFacet = kODNULL;
- fPrintingOpen = kODFalse;
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::~CPrinter
- //---------------------------------------------------------------------------------
-
- CPrinter::~CPrinter()
- {
- WASSERTM(!fPrintingOpen,"Printing was not closed");
- WASSERT(fPrintFacet==kODNULL);
- ODSafeReleaseObject(fSU);
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::Initialize
- //---------------------------------------------------------------------------------
-
- void CPrinter::Initialize( Environment *ev, ODStorageUnit *su )
- {
- ODAcquireObject(ev,su);
- fSU = su;
- fSession = ODGetSession(ev,su);
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::OpenPrinting
- //---------------------------------------------------------------------------------
-
- void CPrinter::OpenPrinting()
- {
- WASSERTM(!fPrintingOpen,"OpenPrinting called twice");
- fPrintingOpen = kODTrue;
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::ClosePrinting
- //---------------------------------------------------------------------------------
-
- void CPrinter::ClosePrinting()
- {
- WASSERTM(fPrintingOpen,"ClosePrinting called twice");
- fPrintingOpen = kODFalse;
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::GetPlatformPrintJob
- //---------------------------------------------------------------------------------
-
- ODPlatformPrintJob CPrinter::GetPlatformPrintJob( Environment* ev )
- {
- // If the print job has not yet been loaded/created, do so now.
- // Try to read a graphics-system-specific value from the standard page-setup property.
- // The platform-specific subclass will do the dirty work of interpreting the
- // data in the value, which we read into a handle for its convenience.
- // If there is no stored page setup or it couldn't be read, make up a new one.
-
- ODPlatformPrintJob job = this->BasicGetPlatformPrintJob( );
-
- if( !job ) {
- CWithPrintingOpen w(this);
-
- TRY
- // Focus the storageUnit to the Print Job property.
- if ( fSU->Exists(ev, kODPropPageSetup, kODNULL, 0) )
- {
- ODValueType valueType = this->GetValueType();
- ODBoolean exists = fSU->Exists(ev,kODPropPageSetup,valueType,0);
- if( !exists ) {
- // Couldn't find main value type, try secondary one:
- valueType = this->GetSecondaryValueType();
- exists = valueType!=kODNULL && fSU->Exists(ev,kODPropPageSetup,valueType,0);
- }
- if( exists ) {
- // Found a value, now read it:
- fSU->Focus(ev, kODPropPageSetup, 0, valueType, 0, kODPosAll);
-
- ODULong size = fSU->GetSize(ev);
- TempODHandle data = ODNewHandle(size);
- StorageUnitGetValue(fSU,ev,size,ODLockHandle(data));
- ODUnlockHandle(data);
- job= this->ReadJobFromHandle(valueType,data.DontDelete());
- }
- }
- CATCH_ALL
- WARN("Error %d internalizing print job",ErrorCode());
- ENDTRY
-
- if( !job ) {
- // Let's just make a new one:
- job= this->CreateNewJob();
- ASSERT(job!=kODNULL,kODErrAssertionFailed);
- }
- }
- return job;
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::Externalize
- //---------------------------------------------------------------------------------
-
- void CPrinter::Externalize( Environment* ev, ODStorageUnit *su /*=kODNULL*/ )
- {
- // su may be different from the part's storage unit (fSU) if the part
- // is being cloned. NULL means use part's storage unit.
-
- if( su==kODNULL ) su=fSU;
-
- if( fDirty || su!=fSU ) {
- CWithPrintingOpen w(this);
- this->GetPlatformPrintJob(ev);
-
- TempODHandle data = this->CopyJobToHandle();
-
- // Focus to / create the Print Job property & value:
- ODSUForceFocus(ev,su,kODPropPageSetup, this->GetValueType());
- ODSize size = su->GetSize(ev);
- if( size>0 )
- su->DeleteValue(ev,size);
- StorageUnitSetValue(su,ev,ODGetHandleSize(data),ODLockHandle(data));
-
- if( su==fSU )
- fDirty = kODFalse;
- }
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::PageSetup
- //---------------------------------------------------------------------------------
-
- ODBoolean CPrinter::PageSetup(Environment* ev)
- {
- ODBoolean success = kODFalse;
-
- TRY
- BusyCursor();
- CWithPrintingOpen w(this);
- CWithDialogState d(ev,fSession);
-
- this->GetPlatformPrintJob(ev);
-
- // Display the Page Setup dialog.
- ODError err = kODNoError;
- TRY{
- success = this->RunPageSetupDialog(ev);
- if( success )
- fDirty = kODTrue;
- }CATCH_ALL{
- err = ErrorCode();
- }ENDTRY
-
- THROW_IF_ERROR(err);
-
- CATCH_ALL
- this->DisplayError(ev, ErrorCode());
- success= kODFalse;
- ENDTRY
- InitCursor();
-
- return success;
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::PrintDocument
- //---------------------------------------------------------------------------------
-
- void CPrinter::PrintDocument(Environment* ev, ODFrame* initiator, ODShape* area /*=kODNULL*/)
- {
- BusyCursor();
-
- // If no area is specified, use the frameshape:
- ODBoolean noAreaSupplied = (area==kODNULL);
- if( noAreaSupplied )
- area = initiator->AcquireFrameShape(ev,kODNULL);
-
- TRY
- CWithDialogState d(ev,fSession);
-
- this->GetPlatformPrintJob(ev);
-
- CWithPrintingOpen w(this);
-
- ODError err = kODNoError;
- TRY{
- if ( this->RunPrintDialog(ev) ) {
- BusyCursor();
- // Create OpenDoc printing geometry objects.
- this->SetupPrintingEnv(ev, initiator, area);
-
- this->DoPrint(ev,area);
- }
- }CATCH_ALL{
- err = ErrorCode();
- }ENDTRY
-
- // Tear down printing objects. We do this here instead of right after DoPrint
- // so that the cleanup will happen even if SetupPrintingEnv or DoPrint throw.
- this->CleanupPrintingEnv(ev, initiator);
- InitCursor();
-
- THROW_IF_ERROR(err); // Reraise the error, if any
-
- CATCH_ALL
- this->DisplayError(ev, ErrorCode());
- // don't reraise...
- ENDTRY
-
- if( noAreaSupplied )
- ODReleaseObject(ev,area);
- }
-
-
- //---------------------------------------------------------------------------------
- // CPrinter::SetupPrintingEnv
- //---------------------------------------------------------------------------------
-
- void CPrinter::SetupPrintingEnv(Environment* ev, ODFrame* initiator, ODShape *area)
- {
- if( fPrintFacet )
- return;
-
- TempODPart part = initiator->AcquirePart(ev);
-
- // Create an external transform for our new facet. It has to counteract the
- // frame's internal transform in case the frame is scrolled/zoomed/whatever.
- TempODTransform xtransform = ODCopyAndRelease(ev,initiator->AcquireInternalTransform(ev,kODNULL));
- xtransform->Invert(ev);
-
- // Create a shape for the clip-shape. It doesn't matter what it is; it'll get
- // set properly in the SetPage method.
- TempODShape clipshape = initiator->CreateShape(ev);
-
- // Get info about the type of canvas to create.
- ODGraphicsSystem arch = this->GetGraphicsSystem();
- ODPlatformCanvas port = this->CreatePrintingPlatformCanvas(ev,arch,initiator,area);
-
- // Get the window state to create objects. We need to do this
- // because we don't have a valid facet yet.
- ODWindowState* windowState = fSession->GetWindowState(ev);
-
- // Creating a printing canvas to add to our new facet.
- ODCanvas* canvas = windowState->CreateCanvas(ev, arch, port, kODFalse, kODFalse);
- TempODObject tempcanvas = canvas; // Make sure it gets deleted on exception
- if( arch != kODQuickDraw ) {
- // Set up QD platform canvas if there isn't one already:
- canvas->SetPlatformCanvas(ev, kODQuickDraw,
- this->CreatePrintingPlatformCanvas(ev,kODQuickDraw,initiator,area));
- }
-
- canvas->SetOwner(ev, part);
- canvas->SetPlatformPrintJob(ev, arch, this->GetPlatformPrintJob(ev));
-
- // Create a printing facet.
- tempcanvas=kODNULL;
- fPrintFacet = windowState->CreateFacet(ev, initiator, clipshape, xtransform,
- canvas, kODNULL);
-
- // Notify the intiator that a printing facet has been added to it.
- TRY{
- initiator->FacetAdded(ev, fPrintFacet);
- }CATCH_ALL{
- // ignore exceptions from part.
- }ENDTRY
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::CleanupPrintingEnv
- //---------------------------------------------------------------------------------
-
- void CPrinter::CleanupPrintingEnv(Environment* ev, ODFrame* initiator)
- {
- // Subclass should override to dispose platform canvas / platform print-job.
-
- if( fPrintFacet ) {
- TRY{
- initiator->FacetRemoved(ev, fPrintFacet);
- }CATCH_ALL{
- }ENDTRY
- ODCanvas *canvas = fPrintFacet->GetCanvas(ev);
- canvas->SetFacet(ev,kODNULL);
- ODDeleteObject(fPrintFacet);
- ODDeleteObject(canvas);
- }
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::CountPages
- //---------------------------------------------------------------------------------
-
- ODULong CPrinter::CountPages(Environment* ev, ODShape* area)
- {
- ODRect contentRect;
- area->GetBoundingBox(ev, &contentRect);
-
- ODRect pageRect = this->GetPageRect(ev);
-
- ODULong horiPages = (contentRect.Width()+pageRect.Width()-1) / pageRect.Width();
- ODULong vertPages = (contentRect.Height()+pageRect.Height()-1) / pageRect.Height();
-
- ODULong pageCount = horiPages * vertPages;
- if( pageCount == 0 )
- pageCount = 1;
-
- return pageCount;
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::SetPage
- //---------------------------------------------------------------------------------
-
- void CPrinter::SetPage(Environment* ev, ODUShort pageNum, ODShape* area)
- {
- ODRect contentRect;
- area->GetBoundingBox(ev, &contentRect);
-
- ODRect pageRect = this->GetPageRect(ev);
-
- // Calc horizontal pages, don't let be less than one
- ODUShort horiPages = (contentRect.Width()+pageRect.Width()-1) / pageRect.Width();
- if (horiPages < 1)
- horiPages = 1;
-
- // Set up a clip-shape to fit the transformed facet:
- TempODShape clipShape = fPrintFacet->CreateShape(ev);
- clipShape->SetRectangle(ev, &pageRect);
- clipShape->Intersect(ev,area); // Restrict to frameshape
-
- // Create an offset which translates the clip shape (page region)
- // back to a {0,0} coordinate space.
- ODPoint offset;
- offset.x = -( contentRect.left + ((pageNum - 1) % horiPages) * pageRect.Width() );
- offset.y = -( contentRect.top + ((pageNum - 1) / horiPages) * pageRect.Height() );
-
- TempODTransform transform = fPrintFacet->AcquireExternalTransform(ev,kODNULL);
- transform->MoveBy(ev, &offset); // Scroll the external transform
-
- clipShape->InverseTransform(ev,transform);
-
- // Update the facet's geometry.
- fPrintFacet->ChangeGeometry(ev, clipShape, transform, fPrintFacet->GetCanvas(ev));
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::PrintPage
- //---------------------------------------------------------------------------------
-
- void CPrinter::PrintPage(Environment* ev, ODUShort page, ODShape *area)
- {
- // Main routine to print a particular page.
-
- this->SetPage(ev, page, area);
- this->OpenPage(ev, page);
-
- TempODShape clip = fPrintFacet->AcquireClipShape(ev, kODNULL);
- fPrintFacet->Update(ev, clip, kODNULL);
-
- this->ClosePage(ev);
- }
-
- //---------------------------------------------------------------------------------
- // CPrinter::DisplayError
- //---------------------------------------------------------------------------------
-
- void CPrinter::DisplayError(Environment* ev, ODSShort error)
- {
- Str255 message;
- Str15 number;
-
- CUsingLibraryResources r;
- CWithDialogState d(ev,fSession);
-
- // Use the default (generic) error message unless we recognize the
- // error number.
- ODUShort index = 1;
- if ( error == -4101 || error == fnfErr )
- index = 2; // no printer selected.
-
- GetIndString(message, rPrintErrorsID, index);
- NumToString(error,number);
- ParamText(message,number,kODNULL,kODNULL);
-
- ShowAlert(ev,rPrintErrorDialog,kODNULL,fSession);
- }
-